1 00:00:00,450 --> 00:00:05,970 Welcome back to get started with scripting our project, we first need to code the two scripts that 2 00:00:05,970 --> 00:00:10,500 are going to be responsible for loading all the modules on the client and on the server. 3 00:00:10,500 --> 00:00:15,630 The plan is to have a table in each of these scripts that keep track of all the modules that have been 4 00:00:15,630 --> 00:00:17,760 loaded, initialized, and started. 5 00:00:17,760 --> 00:00:22,170 The idea is that we're first going to go through and require all the module scripts necessary for the 6 00:00:22,170 --> 00:00:24,330 game, on the client and on the server. 7 00:00:24,330 --> 00:00:28,800 That way when we require the module scripts, it allows us to set up all of the variables and functions 8 00:00:28,800 --> 00:00:29,820 for each module. 9 00:00:29,820 --> 00:00:32,520 The next step would be to initialize all of the modules. 10 00:00:32,520 --> 00:00:37,230 Or basically we're going to let any module script that needs to connect functions to events set themselves 11 00:00:37,230 --> 00:00:40,320 up, or initialize themselves before they start executing code. 12 00:00:40,320 --> 00:00:43,140 It's important that we initialize all of our scripts first. 13 00:00:43,140 --> 00:00:45,570 That way they are ready to start listening to events. 14 00:00:45,570 --> 00:00:50,520 We can create an initialize or init function for the modules that need to connect functions to events. 15 00:00:50,520 --> 00:00:55,110 After we have initialized all of our modules, we're then going to start any that need to be started 16 00:00:55,110 --> 00:01:00,570 or a.k.a any modules that need to continually run some code or functionality like a while loop or firing 17 00:01:00,570 --> 00:01:04,440 events will be started using a start function in the module script. 18 00:01:04,440 --> 00:01:06,030 So let's go ahead and get started. 19 00:01:06,710 --> 00:01:10,040 We're first going to do the start script for the server. 20 00:01:10,040 --> 00:01:11,960 So we're going to go ahead and open this up. 21 00:01:11,960 --> 00:01:16,460 And the only thing we're going to need in here is to reference the server script service. 22 00:01:16,460 --> 00:01:20,270 That way we can reference all of the different folders that are in our server script service. 23 00:01:20,270 --> 00:01:23,390 So get service server script service. 24 00:01:23,660 --> 00:01:27,290 And then we can make a reference to all of these services that are going to be in our game. 25 00:01:27,290 --> 00:01:31,670 So we could do server script service, dot server dot services. 26 00:01:32,150 --> 00:01:35,420 Then I'm going to create a table, I'm going to call it tracker. 27 00:01:35,420 --> 00:01:42,140 And this is going to be responsible for tracking and storing all of the modules that have been loaded. 28 00:01:42,140 --> 00:01:48,410 So we'll create one key value pair for loaded modules we'll have a section for initialize module. 29 00:01:48,410 --> 00:01:50,870 So this will keep track of whether or not they have been initialized. 30 00:01:50,870 --> 00:01:56,360 And then we're going to have a section for started modules or whether or not they've been started yet. 31 00:01:56,570 --> 00:02:01,430 Then the next thing I'm going to do is I'm going to create a two private functions that are going to 32 00:02:01,430 --> 00:02:03,680 override the print and warn function. 33 00:02:03,680 --> 00:02:05,840 So I'm just going to call this one new print. 34 00:02:06,080 --> 00:02:10,310 And it's going to take a variable number of arguments just like the regular print function. 35 00:02:10,310 --> 00:02:13,070 And all we're going to do is call the print function. 36 00:02:13,070 --> 00:02:19,160 And we're going to put a string in here, which is a bracket S bracket, to indicate that this message 37 00:02:19,160 --> 00:02:20,420 is coming from the server. 38 00:02:20,420 --> 00:02:25,370 And then we could just put a comma and pass all of the other arguments that were passed to our new print 39 00:02:25,370 --> 00:02:26,210 function. 40 00:02:26,210 --> 00:02:31,100 And then we could do the exact same thing, but we could do it for the warn function. 41 00:02:31,100 --> 00:02:37,940 So new warn and we'll just warn again on the server whatever we want to send to this function. 42 00:02:37,940 --> 00:02:42,950 Now let's go ahead and create some functions for loading, starting and initializing our modules. 43 00:02:42,950 --> 00:02:46,130 So we'll have a function to uh load a module. 44 00:02:46,130 --> 00:02:47,750 So we'll call this load module. 45 00:02:47,750 --> 00:02:49,880 And we'll pass a module script to it. 46 00:02:49,970 --> 00:02:53,750 We're going to have a function to initialize a module. 47 00:02:53,750 --> 00:02:57,590 So we could call it initialize module. 48 00:02:57,590 --> 00:03:00,650 And this will pass a. 49 00:03:01,360 --> 00:03:02,260 Loaded module. 50 00:03:02,260 --> 00:03:07,630 So we'll get the table of the module script that was loaded, as well as the name of the module script, 51 00:03:07,630 --> 00:03:08,980 and you'll see why in a moment. 52 00:03:10,090 --> 00:03:13,600 And then we're going to do the same thing for starting a module. 53 00:03:13,600 --> 00:03:19,270 So start module we'll get this loaded module and the name of the module as well. 54 00:03:20,170 --> 00:03:24,970 So basically what we're going to do down here in this main section is we're going to call our new Warn 55 00:03:24,970 --> 00:03:25,690 function. 56 00:03:25,690 --> 00:03:30,730 And we're going to send out a message in the console saying that we're starting up the server so we 57 00:03:30,730 --> 00:03:37,600 can do something like starting server and say something like we're loading the services in our game. 58 00:03:37,750 --> 00:03:43,780 So the first thing that we would do is that we loop through every single module script that is inside 59 00:03:43,780 --> 00:03:45,250 of our services folder. 60 00:03:45,250 --> 00:03:48,640 So we would get all of the children and our services folder. 61 00:03:49,370 --> 00:03:54,650 And then what we would do is we would call the load module function and pass that module script to it. 62 00:03:54,650 --> 00:03:59,390 So all of the services that are going to exist in here are going to get loaded. 63 00:03:59,390 --> 00:04:05,600 And then after we've loaded all of them, then we can copy this message again and send out another warning 64 00:04:05,600 --> 00:04:08,420 that we're now going to initialize modules. 65 00:04:08,420 --> 00:04:12,500 So we could do initializing modules. 66 00:04:12,500 --> 00:04:19,940 And then we can loop through every single loaded module that's going to be inside of the initialize 67 00:04:19,940 --> 00:04:20,360 table. 68 00:04:20,360 --> 00:04:24,260 So it's going to check to see what module scripts need to be initialized. 69 00:04:24,260 --> 00:04:26,000 And it's going to initialize them. 70 00:04:26,000 --> 00:04:29,930 So the idea is that we're going to have a module name stored in there. 71 00:04:31,460 --> 00:04:34,430 And what we're going to do. 72 00:04:35,780 --> 00:04:39,710 As we're going to loop through all those modules that need to be initialized, and then we'll call the 73 00:04:39,710 --> 00:04:41,390 initialize module function. 74 00:04:41,390 --> 00:04:47,660 And then what we're going to do is we're going to need to pass the loaded module that we can call the 75 00:04:47,660 --> 00:04:50,030 initialize function within that module script. 76 00:04:50,030 --> 00:04:56,870 So that means inside of our load table we're going to have it stored in here using the modules name. 77 00:04:57,410 --> 00:05:00,380 And then we can just pass the name of the module itself as well. 78 00:05:00,380 --> 00:05:02,660 So we'll do something like that. 79 00:05:03,350 --> 00:05:07,970 And then we're going to do basically the same thing, but for starting our module. 80 00:05:07,970 --> 00:05:10,280 So this section will be for starting modules. 81 00:05:10,280 --> 00:05:12,980 There will be all stored inside of the start table. 82 00:05:13,630 --> 00:05:16,600 And instead we need to start a module. 83 00:05:16,600 --> 00:05:23,020 And then once we finally have loaded, initialized and started our modules, then we can warn one last 84 00:05:23,020 --> 00:05:25,810 time that we have finished loading the server. 85 00:05:25,810 --> 00:05:28,420 We could say server loading finished. 86 00:05:29,000 --> 00:05:33,170 And then what I'm going to do is I'm going to set a attribute on the workspace. 87 00:05:33,170 --> 00:05:37,820 So set attribute we can just call it something like server loaded. 88 00:05:37,820 --> 00:05:39,440 And we're going to set this to true. 89 00:05:39,440 --> 00:05:43,970 And this is to let the client know that the server has finished loading and setting up all of these 90 00:05:43,970 --> 00:05:44,750 scripts. 91 00:05:45,140 --> 00:05:49,460 So let's go ahead and fill out these functions right here to load a module. 92 00:05:49,460 --> 00:05:56,180 The first thing I want to do is I want to calculate how long it took to load this module. 93 00:05:56,180 --> 00:05:58,430 So we're going to have a start time. 94 00:05:58,430 --> 00:06:01,340 And we're going to use the tick function to get the starting time. 95 00:06:01,340 --> 00:06:05,210 And then we're going to use our new print function to print out into the console. 96 00:06:05,210 --> 00:06:08,300 And we can say something like loading module. 97 00:06:08,300 --> 00:06:12,260 And we're going to put a couple other quotations. 98 00:06:12,260 --> 00:06:14,810 And then we're going to put a directive in here as a string. 99 00:06:14,810 --> 00:06:18,500 And we're going to format this with the modules name. 100 00:06:19,070 --> 00:06:23,150 So we're loading module for example uh Squidward service. 101 00:06:24,170 --> 00:06:29,510 And then what we're going to do is we're going to use a p call and pass a function in here. 102 00:06:29,510 --> 00:06:36,320 And we're going to require our module script so we can get the loaded module using the require function 103 00:06:36,320 --> 00:06:38,000 and pass the module script. 104 00:06:39,270 --> 00:06:43,650 And then what we could do is put inside of the load table, this module. 105 00:06:43,650 --> 00:06:47,340 And we're going to create a key value pair using the modules name. 106 00:06:47,340 --> 00:06:52,440 And at that key we're going to store the table that was returned from our module script. 107 00:06:52,440 --> 00:06:57,900 So that way we can access it here and here and pass it to our initialize and start module functions. 108 00:06:57,900 --> 00:07:03,060 The next thing we need to do is we need to check if this module script has an initialize function. 109 00:07:03,060 --> 00:07:11,700 So if this loaded module inside of this table has a key for initializing or init, then what we need 110 00:07:11,700 --> 00:07:14,460 to do is inside of tracker dot init. 111 00:07:14,460 --> 00:07:20,820 We need to create a key value pair for this module, and we're going to set it to false, meaning it 112 00:07:20,820 --> 00:07:24,390 hasn't been initialized yet, but we need to initialize it in the future. 113 00:07:24,390 --> 00:07:30,330 And then we're going to do the exact same thing and check to see if this module has a start function. 114 00:07:30,600 --> 00:07:35,010 If it does, then we're going to basically do the exact same thing. 115 00:07:35,010 --> 00:07:37,440 We can let me actually copy this. 116 00:07:37,440 --> 00:07:42,420 So instead of storing it in the initialize table we're going to do this in the start table. 117 00:07:42,780 --> 00:07:48,300 And the reason I'm using a p call in this is just in case this module script we're trying to require 118 00:07:48,300 --> 00:07:48,720 errors. 119 00:07:48,720 --> 00:07:51,900 For some reason we don't want to halt our entire game. 120 00:07:51,900 --> 00:07:58,650 We only want to have the code stop in that particular module script so we can store the result from 121 00:07:58,650 --> 00:07:59,250 this function. 122 00:07:59,250 --> 00:08:01,950 So success and result from this p call. 123 00:08:03,300 --> 00:08:10,200 And then once we're done loading this module, then we're also going to get the end time using the tick 124 00:08:10,200 --> 00:08:10,950 function. 125 00:08:11,040 --> 00:08:15,000 And what we could do here is look to see if we were successful in loading our module script. 126 00:08:15,000 --> 00:08:22,530 So if success then we're going to use the new print function and print out a message like uh, I'm going 127 00:08:22,530 --> 00:08:29,430 to indent it with like two vertical bars and say we loaded a module and put a directive here for the 128 00:08:29,430 --> 00:08:31,260 name of the module. 129 00:08:31,650 --> 00:08:35,850 And we can format this with module dot name. 130 00:08:35,850 --> 00:08:37,650 So we loaded this module. 131 00:08:37,830 --> 00:08:42,000 And then we're going to pass a second string to our new print function. 132 00:08:42,000 --> 00:08:47,580 And we can say something like it took uh we're going to put a directive here. 133 00:08:47,580 --> 00:08:51,030 So we're going to do percentage point three and then F. 134 00:08:51,030 --> 00:08:57,390 So we're going to put a floating point number here with a three decimal point uh accuracy. 135 00:08:57,960 --> 00:09:00,270 And we're going to say it took this many seconds. 136 00:09:01,070 --> 00:09:06,740 And we can format this again and pass the end time minus the start time. 137 00:09:06,740 --> 00:09:12,440 So we get exactly how long it took for us to load this module script. 138 00:09:12,770 --> 00:09:18,590 Otherwise, if we fail to load this module script we encountered an error. 139 00:09:18,590 --> 00:09:23,720 Then what we're going to do is we're going to pass a message here using our Warn function instead. 140 00:09:24,260 --> 00:09:28,580 And we're going to say something like failed to load module. 141 00:09:29,150 --> 00:09:30,800 We'll pass the time. 142 00:09:30,920 --> 00:09:35,390 And then what else I'm going to do is, um. 143 00:09:35,570 --> 00:09:35,810 Oops. 144 00:09:35,810 --> 00:09:40,190 Let me actually, uh, make sure to put these parentheses here. 145 00:09:40,190 --> 00:09:46,190 But what am I going to do is I'm going to pass a backslash and then n to indicate a new line. 146 00:09:46,190 --> 00:09:49,040 And I'm going to put another directive here which is going to be a string. 147 00:09:49,040 --> 00:09:50,330 So percentage s. 148 00:09:51,070 --> 00:09:54,130 And that means we're also going to pass the error message. 149 00:09:54,130 --> 00:09:57,250 So we're going to pass the result from our Pcall function. 150 00:09:57,710 --> 00:10:02,990 So if our module fails to load, it's going to tell us failed to load module like Squidward. 151 00:10:02,990 --> 00:10:08,240 Service took however many seconds and then on a new line, it's going to tell us exactly what the error 152 00:10:08,240 --> 00:10:09,560 was in that module script. 153 00:10:10,230 --> 00:10:13,530 And that's all we need to do for our load module function. 154 00:10:14,000 --> 00:10:17,900 Now what do we need to do for initializing our module script? 155 00:10:17,930 --> 00:10:23,390 Well, in here, the first thing I want to check is whether or not the module that was passed to this 156 00:10:23,390 --> 00:10:25,730 function has an initialize function. 157 00:10:25,730 --> 00:10:26,720 If it doesn't. 158 00:10:26,720 --> 00:10:31,280 So if not loaded module dot init, then we're just going to return. 159 00:10:32,000 --> 00:10:33,320 That's all we want to do. 160 00:10:33,680 --> 00:10:39,500 Otherwise we can print inside of the console that we are initializing a module. 161 00:10:39,500 --> 00:10:44,240 So initializing module percentage s. 162 00:10:45,670 --> 00:10:49,330 And we can format this with the modules name. 163 00:10:49,870 --> 00:10:55,810 And actually we can move the start time up here to be in front of when we print in the console. 164 00:10:55,840 --> 00:11:00,010 Because I do know that formatting a string takes a little bit of time. 165 00:11:00,010 --> 00:11:01,330 So to make it more accurate. 166 00:11:02,000 --> 00:11:06,410 We'll print it out first and then get the start time up here, and then we can do the same thing down 167 00:11:06,410 --> 00:11:06,980 here. 168 00:11:06,980 --> 00:11:12,950 So we print out we're initializing this module and I'll put more parentheses here for the name. 169 00:11:13,760 --> 00:11:15,650 We'll get the start time. 170 00:11:17,200 --> 00:11:19,300 And we're going to do the same thing with a P call. 171 00:11:19,300 --> 00:11:22,390 So we're going to have two variables for success and results. 172 00:11:24,660 --> 00:11:29,790 And all we're going to do is on this loaded module, we're going to call its init function. 173 00:11:30,620 --> 00:11:39,470 And once it's done initializing, then we can set inside of tracker dot init module uh name equal to 174 00:11:39,470 --> 00:11:40,280 true. 175 00:11:40,280 --> 00:11:44,600 And then once that's done, we can get the end time equal to tick. 176 00:11:45,180 --> 00:11:48,450 And we're basically going to do the exact same thing that we did here. 177 00:11:48,450 --> 00:11:52,380 We're going to print out that we have initialized a module. 178 00:11:52,380 --> 00:12:00,810 So initialized module format it with the module name say how many seconds it took. 179 00:12:01,810 --> 00:12:06,970 And then if we fail to initialize it, we're going to say failed to initialize. 180 00:12:08,250 --> 00:12:11,460 Module, format it with the modules name. 181 00:12:11,460 --> 00:12:13,050 So module name. 182 00:12:14,420 --> 00:12:19,970 How many seconds it took, and then format it with the time and the result from the P call. 183 00:12:20,530 --> 00:12:24,100 And then lastly, we can do the exact same thing with our start module. 184 00:12:24,860 --> 00:12:31,550 If this module does not have a start function, then we're just going to return. 185 00:12:32,240 --> 00:12:38,060 Otherwise, we can again use the new print function and print out something like starting module. 186 00:12:38,660 --> 00:12:40,250 Put a directive in here. 187 00:12:42,480 --> 00:12:46,080 And actually let me put extra parentheses around it so we can format it. 188 00:12:46,410 --> 00:12:49,770 Call the format function and pass the module name. 189 00:12:51,240 --> 00:12:57,180 Another P call success result equal to p call pass a lambda function. 190 00:12:57,180 --> 00:13:00,180 And in this we're going to do the same thing. 191 00:13:00,180 --> 00:13:03,060 Except we're going to call the start function in the module. 192 00:13:03,060 --> 00:13:09,000 And then we could just do tracker dot start pass the module name and set that key value pair to true. 193 00:13:11,160 --> 00:13:13,350 Then we can get the end time. 194 00:13:13,950 --> 00:13:17,100 And actually let me get the start time up here as well. 195 00:13:20,100 --> 00:13:26,220 Get the start time and time, and then we can do literally the exact same thing that we did here, but 196 00:13:26,220 --> 00:13:33,060 instead we're going to say started module whatever and then fail to start module. 197 00:13:33,330 --> 00:13:34,980 And that's all we need to do. 198 00:13:34,980 --> 00:13:40,980 So if I go ahead and run my game, uh, it should only initialize our modules because they're empty 199 00:13:40,980 --> 00:13:41,880 and that's it. 200 00:13:41,880 --> 00:13:45,690 It won't uh, it won't start any modules and it won't initialize any modules. 201 00:13:45,690 --> 00:13:47,040 It'll just load them. 202 00:13:47,040 --> 00:13:54,450 So if we go and play test or just run the game, we should see in the console that we. 203 00:13:54,450 --> 00:13:55,470 Let's see. 204 00:13:56,960 --> 00:13:58,010 Loaded a module. 205 00:13:58,010 --> 00:14:00,950 We failed to load it because it didn't return anything because they're empty. 206 00:14:00,980 --> 00:14:04,130 Loaded module list failed to load it because it didn't return anything. 207 00:14:04,130 --> 00:14:07,910 And then initializing modules is empty along with starting modules. 208 00:14:07,910 --> 00:14:10,100 And then we finished loading the server. 209 00:14:10,130 --> 00:14:11,090 Very cool. 210 00:14:11,120 --> 00:14:15,830 Now the fun part about this is we can literally just copy all of the code that we've done in here. 211 00:14:16,220 --> 00:14:18,050 So copy all of it. 212 00:14:18,050 --> 00:14:20,150 And we're going to go to our local script. 213 00:14:20,150 --> 00:14:22,220 And we're just going to paste it all in here. 214 00:14:22,220 --> 00:14:24,950 And we're just going to make a couple changes. 215 00:14:24,950 --> 00:14:27,800 So we can't require the server script service. 216 00:14:27,800 --> 00:14:30,440 So instead what we need to require is the player service. 217 00:14:30,440 --> 00:14:34,100 So we could do players get service players. 218 00:14:34,520 --> 00:14:40,640 And then to get access to all of the handlers on the client I'll rename this to handlers. 219 00:14:40,640 --> 00:14:49,970 We're just going to get players dot local player access our player scripts folder and then access the 220 00:14:49,970 --> 00:14:50,900 client folder. 221 00:14:50,900 --> 00:14:53,090 And inside of there the handlers folder. 222 00:14:53,090 --> 00:14:58,820 And I do not need to use wait for child because this script is only going to execute once everything 223 00:14:58,820 --> 00:15:00,350 has been replicated. 224 00:15:00,350 --> 00:15:05,690 And of course the script is only going to execute once it's actually part of the player instance. 225 00:15:05,690 --> 00:15:07,850 So all of this stuff is going to be loaded. 226 00:15:07,850 --> 00:15:10,010 I don't have to use wait for child on it at all. 227 00:15:11,080 --> 00:15:13,990 We're going to have the exact same tracker table in here. 228 00:15:13,990 --> 00:15:16,630 And I'm going to rename this with C. 229 00:15:16,630 --> 00:15:19,150 So we know this is being printed on the client. 230 00:15:20,190 --> 00:15:25,680 We'll basically do the exact same thing for loading the module, initializing a module, and starting 231 00:15:25,680 --> 00:15:26,580 a module. 232 00:15:26,820 --> 00:15:34,260 And then what we could do instead is just get all of the module scripts in our handlers folder, load 233 00:15:34,260 --> 00:15:36,330 it, initialize them and start them. 234 00:15:36,330 --> 00:15:40,680 And we can just change these words here to starting client. 235 00:15:41,510 --> 00:15:44,720 And loading handlers. 236 00:15:44,780 --> 00:15:47,240 Initializing modules starting modules. 237 00:15:47,240 --> 00:15:50,870 And then we can say client loading finished. 238 00:15:51,170 --> 00:15:56,210 And we can set the attribute on the workspace that we have loaded the client successfully. 239 00:15:56,450 --> 00:16:02,090 However, before we load the client, we need to make sure that the server is loaded first. 240 00:16:02,090 --> 00:16:09,500 So inside of our main section here before we do anything, if in the workspace we get the attribute 241 00:16:09,500 --> 00:16:15,770 server loaded and it's false or it doesn't exist yet, then we need to wait for the server to load so 242 00:16:15,770 --> 00:16:23,240 we can do workspace, get attribute changed signal, and we're going to wait for the server to load. 243 00:16:25,020 --> 00:16:25,830 And that's it. 244 00:16:25,830 --> 00:16:30,510 So once the server is loaded, then we can start up the client and we should be good to go. 245 00:16:30,510 --> 00:16:32,640 So that means if we play test our game. 246 00:16:32,640 --> 00:16:34,200 So if we do play. 247 00:16:35,530 --> 00:16:42,010 Of course we're going to see that the server loaded and started up, loaded the modules, blah blah, 248 00:16:42,010 --> 00:16:42,490 blah. 249 00:16:42,490 --> 00:16:48,040 And then once the server loading finished, then we started the client and required all those modules. 250 00:16:48,040 --> 00:16:48,940 Very cool. 251 00:16:49,780 --> 00:16:54,340 So this is exactly how we are going to organize the scripts in our game. 252 00:16:54,340 --> 00:16:59,590 We're going to have modules that have their own purpose for a specific thing on the client and server, 253 00:16:59,590 --> 00:17:06,100 and we'll have a section for any modules that need to be shared between other services and handlers. 254 00:17:06,100 --> 00:17:11,200 So if any of these handlers or services in here need to access some shared code, they can access them 255 00:17:11,200 --> 00:17:12,610 in the modules folder. 256 00:17:12,610 --> 00:17:17,380 And if any services or handlers need to communicate with another service or handler, then they're going 257 00:17:17,380 --> 00:17:19,540 to do that through bindable events. 258 00:17:19,900 --> 00:17:23,710 Other than that, we have the client and server loading set up. 259 00:17:23,710 --> 00:17:27,250 And this is exactly how we are going to structure out our horror game. 260 00:17:27,280 --> 00:17:28,780 See you in the next one.